package com;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 验证码帮助类
 */
public class ValidateCodeHelper {

    private static final char[] CODES = { 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'J', 'K', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

    private static final Random R = new Random();
    private static final double THETA = Math.PI / 15;

    /**
     *
     * 生成随机码
     *
     * @param length
     *            长度
     * @return
     */
    public static String generateCode(int length) {
        StringBuilder code = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            code.append(CODES[random.nextInt(CODES.length)]);
        }
        return code.toString();
    }

    /**
     * 生成图片
     *
     * @param code
     *            验证码
     * @param imageWidth
     *            图片宽度
     * @param imageHeight
     *            图片高度
     * @param fontSize
     *            字体大小
     * @return
     */
    public static BufferedImage drawImage(String code, int imageWidth, int imageHeight, int fontSize) {
        return drawImage(code, imageWidth, imageHeight, new Font("Book Antiqua", Font.PLAIN, fontSize));
    }

    /**
     * 生成图片
     *
     * @param code
     *            验证码
     * @param imageWidth
     *            图片宽度
     * @param imageHeight
     *            图片高度
     * @param font
     *            字体
     * @return
     */
    public static BufferedImage drawImage(String code, int imageWidth, int imageHeight, Font font) {
        BufferedImage buffImg = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffImg.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, imageWidth, imageHeight);
        g.setFont(font);
        g.setColor(Color.BLACK);

        imageWidth = imageWidth - 4;
        imageHeight = imageHeight - 4;

        Color[] colors = getRandomColors(6);

        int fontSize = font.getSize();
        int x1;
        int y1;
        int x2;
        int y2;
        // 干扰线
        for (int i = 0; i < 5; i++) {
            x1 = R.nextInt(imageWidth);
            y1 = R.nextInt(imageHeight);
            x2 = R.nextInt(12);
            y2 = R.nextInt(12);
            g.setColor(colors[R.nextInt(2)]);
            g.drawLine(x1, y1, x1 + x2, y1 + y2);
        }

        // 噪点
        int noisyQty = (int) (imageHeight * imageWidth * 0.01f);
        for (int i = 0; i < noisyQty; i++) {
            x1 = R.nextInt(imageWidth);
            y1 = R.nextInt(imageHeight);
            x2 = R.nextInt(2) + 1;
            g.setColor(colors[R.nextInt(3)]);
            g.fillRect(x1, y1, x2, 1);
        }

        float codeWidth = imageWidth * 1.00f / code.length();
        float codeMaxY = (imageHeight + fontSize) * 1.00f / 2;
        int offsetX = (int) (codeWidth * 0.2);
        int offsetY = (int) (codeMaxY * 0.3);

        float x;
        float y;
        for (int i = 0, len = code.length(); i < len; i++) {
            if (i == 0) {
                x = 1;
            } else {
                x = (i * codeWidth) - random(R, offsetX);
            }
            if (i == len - 1) {
                if (R.nextInt(2) == 1) {
                    y = codeMaxY - offsetY;
                    // 旋转文本
                    g.rotate(THETA, (x + codeWidth) / 2, imageHeight / 2);
                } else {
                    y = codeMaxY;
                    g.rotate(-THETA, (x + codeWidth) / 2, imageHeight / 2);
                }
            } else {
                y = Math.min(codeMaxY - random(R, offsetY), codeMaxY);
            }
            g.setColor(colors[i + 2]); // 可能跟噪点重用1种颜色
            g.drawString(String.valueOf(code.charAt(i)), x, y);
        }

        return buffImg;
    }

    private static int random(Random r, int n) {
        if (n == 0) {
            return 0;
        }
        return n - r.nextInt(n * 2);
    }

    private static Color[] getRandomColors(int size) {
        Color[] colors = new Color[size];
        int red = 0;
        int green = 0;
        int blue = 0;
        for (int i = 0; i < size; i++) {
            red = R.nextInt(200);
            green = R.nextInt(180);
            blue = R.nextInt(255);
            colors[i] = new Color(red, green, blue);
        }
        return colors;
    }
}